<!DOCTYPE html>
<html>

<head>
    <title>extrudelinetrail test</title>
    <script type="text/javascript" src="https://unpkg.com/dat.gui@0.7.6/build/dat.gui.min.js"></script>
    <link type="text/css" rel="stylesheet" href="https://unpkg.com/maptalks/dist/maptalks.css">
    <script type="text/javascript" src="https://unpkg.com/maptalks/dist/maptalks.js"></script>
    <script type="text/javascript" src="https://unpkg.com/three@0.138.0/build/three.min.js"></script>
    <script type="text/javascript"
        src="https://unpkg.com/three@0.138.0/examples/js/libs/stats.min.js"></script>
    <script type="text/javascript" src="https://unpkg.com/lz-string@1.4.4/libs/lz-string.min.js"></script>
    <script type="text/javascript" src="https://unpkg.com/maptalks.three@latest/dist/maptalks.three.js"></script>
    <script type="text/javascript" src="js/geoutil.js"></script>
    <script type="text/javascript" src="buildings.js"></script>
    <style>
        html,
        body {
            margin: 0px;
            height: 100%;
            width: 100%;
        }

        #map {
            width: 100%;
            height: 100%;
            background-color: #000;
        }
    </style>
</head>

<body>
    <div id="map"></div>
    <script>


        var map = new maptalks.Map("map", {
            center: [13.416935229170008, 52.529564137540376],
            zoom: 15,
            pitch: 70,
            bearing: 180,
            centerCross: true,
            doubleClickZoom: false,
            // baseLayer: new maptalks.TileLayer('tile', {
            //     urlTemplate: 'https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png',
            //     subdomains: ['a', 'b', 'c', 'd'],
            //     attribution: '&copy; <a href="http://osm.org">OpenStreetMap</a> contributors, &copy; <a href="https://carto.com/">CARTO</a>'
            // })
        });
        // features to draw
        var features = [];
        buildings.forEach(function (b) {
            features = features.concat(b.features);
        });
        // the ThreeLayer to draw buildings
        var threeLayer = new maptalks.ThreeLayer('t', {
            forceRenderOnMoving: true,
            forceRenderOnRotating: true,
            // animation: true
        });
        var stats;
        threeLayer.prepareToDraw = function (gl, scene, camera) {
            stats = new Stats();
            stats.domElement.style.zIndex = 100;
            document.getElementById('map').appendChild(stats.domElement);

            var light = new THREE.DirectionalLight(0xffffff);
            light.position.set(0, -10, 10).normalize();
            scene.add(light);
            var material = new THREE.MeshBasicMaterial({ color: '#3e35cf' });
            var meshs = [];
            features.forEach(function (g) {
                var heightPerLevel = 10;
                var levels = g.properties.levels || 1;
                var mesh = threeLayer.toExtrudePolygon(maptalks.GeoJSON.toGeometry(g), {
                    height: heightPerLevel * levels,
                    topColor: '#fff',
                    interactive: false
                }, material);
                meshs.push(mesh);
            });
            threeLayer.addMesh(meshs);
            addLines();
        };
        threeLayer.addTo(map);

        var material = new THREE.MeshBasicMaterial({ color: 0xd3887, transparent: true });
        var highlightmaterial = new THREE.MeshBasicMaterial({ color: 0x00ffff, transparent: true });
        var lines, lineTrails;
        function addLines() {
            fetch('./data/berlin-roads.txt').then(function (res) {
                return res.text();
            }).then(function (geojson) {
                geojson = LZString.decompressFromBase64(geojson);
                geojson = JSON.parse(geojson);
                var lineStrings = maptalks.GeoJSON.toGeometry(geojson);
                var timer = 'generate line time';
                console.time(timer);
                const list = [];
                lineStrings.forEach(lineString => {
                    list.push({
                        lineString,
                        len: lineLength(lineString)
                    });
                });
                lineStrings = list.sort(function (a, b) {
                    return b.len - a.len
                });

                lines = lineStrings.slice(0, 1000).map(d => {
                    var line = threeLayer.toExtrudeLine(d.lineString, { altitude: 0, width: 3, height: 1 }, material);
                    return line;
                });
                lineTrails = lineStrings.slice(0, 300).map(function (d) {
                    var line = threeLayer.toExtrudeLineTrail(d.lineString, { altitude: 0, width: 3, height: 2, chunkLength: d.len / 40, speed: 1, trail: 6 }, highlightmaterial);
                    return line;
                });

                console.log('lines.length:', lines.length);
                console.timeEnd(timer);
                threeLayer.addMesh(lines);
                threeLayer.addMesh(lineTrails);
                initGui();
                // threeLayer.config('animation', true);
                animation();
            })
        }

        function animation() {
            // layer animation support Skipping frames
            threeLayer._needsUpdate = !threeLayer._needsUpdate;
            if (threeLayer._needsUpdate) {
                threeLayer.redraw();
            }
            stats.update();
            requestAnimationFrame(animation);
        }


        function initGui() {
            var params = {
                add: true,
                color: highlightmaterial.color.getStyle(),
                show: true,
                opacity: 1,
                altitude: 0
            };
            var gui = new dat.GUI();
            gui.add(params, 'add').onChange(function () {
                if (params.add) {
                    threeLayer.addMesh(lineTrails);
                } else {
                    threeLayer.removeMesh(lineTrails);
                }
            });
            gui.addColor(params, 'color').name('line color').onChange(function () {
                highlightmaterial.color.set(params.color);
                lineTrails.forEach(function (mesh) {
                    mesh.setSymbol(highlightmaterial);
                });
            });
            gui.add(params, 'opacity', 0, 1).onChange(function () {
                highlightmaterial.opacity = params.opacity;
                lineTrails.forEach(function (mesh) {
                    mesh.setSymbol(highlightmaterial);
                });
            });
            gui.add(params, 'show').onChange(function () {
                lineTrails.forEach(function (mesh) {
                    if (params.show) {
                        mesh.show();
                    } else {
                        mesh.hide();
                    }
                });
            });
            gui.add(params, 'altitude', 0, 300).onChange(function () {
                lineTrails.forEach(function (mesh) {
                    mesh.setAltitude(params.altitude);
                });
            });
        }
    </script>
</body>

</html>